package com.user.mediacoderdemo;

import android.media.MediaCodec;
import android.media.MediaCrypto;
import android.media.MediaFormat;
import android.os.Build;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.view.Surface;

import java.nio.ByteBuffer;

/**
 * Created by zoudong on 2017/2/11.
 * 兼容 MedioCodec Decodec
 */

public abstract class AbsMediaCodecWraper {


    private MediaCodec mDecoder = null;

    public AbsMediaCodecWraper(String type) {
        mDecoder = createMediaCodec(type);
    }

    abstract MediaCodec createMediaCodec(String type);

    public void configure(@Nullable MediaFormat format,
                          @Nullable Surface surface, @Nullable MediaCrypto crypto, int flags) {
        if (mDecoder != null) {
            mDecoder.configure(format, surface, crypto, flags);
        }
    }

    public void start() {
        if (mDecoder != null) {
            mDecoder.start();
        }
    }

    public int dequeueInputBuffer(long timeout) {
        try{
                return mDecoder.dequeueInputBuffer(timeout);
        } catch (IllegalStateException e) {
            setOnErrorListener(1, 1);
        }
        return -4;
    }

    public ByteBuffer getInputBuffer(int index) {
        try {
            if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
                return mDecoder.getInputBuffers()[index];
            } else {
                return mDecoder.getInputBuffer(index);
            }
        } catch (IllegalStateException e) {
            setOnErrorListener(1, 1);
        }
        return null;
    }

    public int dequeueOutputBuffer(long timeout) {
        try {
            MediaCodec.BufferInfo info = new MediaCodec.BufferInfo();
            return mDecoder.dequeueOutputBuffer(info, timeout);
        } catch (IllegalStateException e) {
            setOnErrorListener(1, 1);
        }
        return -4;
    }

    public int dequeueOutputBuffer(MediaCodec.BufferInfo info, long timeout) {
        try {
            if (info == null) {
                info = new MediaCodec.BufferInfo();
            }
            return mDecoder.dequeueOutputBuffer(info, timeout);
        } catch (IllegalStateException e) {
            setOnErrorListener(1, 1);
        }
        return -4;
    }

    public MediaFormat getOutputFormat() {
        return mDecoder.getOutputFormat();
    }

    public ByteBuffer getOutputBuffer(int index) {
        try {
            if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
                return mDecoder.getOutputBuffers()[index];
            } else {
                return mDecoder.getOutputBuffer(index);
            }
        } catch (IllegalStateException e) {
            setOnErrorListener(1, 1);
        }
        return null;
    }

    public void flush() {
        mDecoder.flush();
    }

    /**
     * queue data to the input buffer of codec
     */
    public void queueInputBuffer(int inIndex, int offset, int size, long presentationTimeUs, int flags) {
        try {
            mDecoder.queueInputBuffer(inIndex, offset, size, presentationTimeUs, flags);
        } catch (IllegalStateException e) {
            setOnErrorListener(1, 1);
        }

    }

    public void releaseOutputBuffer(int index, boolean render) {
        try{
            mDecoder.releaseOutputBuffer(index, render);
        } catch (IllegalStateException e) {
            setOnErrorListener(1, 1);
        }

    }

    public void stop() {
        try{
             mDecoder.stop();
        } catch (IllegalStateException e) {
            setOnErrorListener(1, 1);
        }
    }

    public void release() {
        try{
            mDecoder.release();
        } catch (IllegalStateException e) {
            setOnErrorListener(1, 1);
        }
    }

    /**
     * -------- 加载 进度-------------
     */
    public interface OnBufferingUpdateListener {
        void onBufferingUpdate(AbsMediaCodecWraper mp, int percent);
    }

    public void setOnBufferingUpdateListener(OnBufferingUpdateListener listener) {
        mOnBufferingUpdateListener = listener;
    }

    public void setOnBufferingUpdateListener(int percent) {
        if (mOnBufferingUpdateListener != null) {
            mOnBufferingUpdateListener.onBufferingUpdate(this, percent);
        }
    }

    public void setOnPlayeringUpdateListener(long currtime, long totaltime) {
        if (mOnPlayeringUpdateListener != null) {
            mOnPlayeringUpdateListener.onBufferingUpdate(this, currtime, totaltime);
        }
    }

    public void setOnCompletionListener() {
        if (onCompletionListener != null) {
            onCompletionListener.onCompletion();
        }
    }

    public void setOnErrorListener(int what, int extra) {
        if (mOnErrorListener != null) {
            mOnErrorListener.onError(what, extra);
        }
    }


    private OnBufferingUpdateListener mOnBufferingUpdateListener;

    /**
     * --------- 播放进度--------------
     */
    public interface OnPlayeringUpdateListener {
        void onBufferingUpdate(AbsMediaCodecWraper mp, long currtime, long totaltime);
    }

    public void setOnPlayeringUpdateListener(OnPlayeringUpdateListener listener) {
        mOnPlayeringUpdateListener = listener;
    }

    private OnPlayeringUpdateListener mOnPlayeringUpdateListener;

    /**
     * --------- 播放完成--------------
     */
    public interface OnCompletionListener {
        void onCompletion();
    }

    public void setOnCompletionListener(OnPlayeringUpdateListener listener) {
        mOnPlayeringUpdateListener = listener;
    }

    private OnCompletionListener onCompletionListener;

    /**
     * ------------ 错误--------------
     **/
    public interface OnErrorListener {
        void onError(int what, int extra);
    }

    public void setOnErrorListener(OnErrorListener listener) {
        mOnErrorListener = listener;
    }

    private OnErrorListener mOnErrorListener;
}
